package com.agua.enturno.servicios.impl;

import com.agua.enturno.excepciones.ExcepcionDeReglaDelNegocio;
import com.agua.enturno.modelo.roles.Cliente;
import com.agua.enturno.modelo.roles.Usuario;
import com.agua.enturno.persistencia.dao.UsuarioDAO;
import com.agua.enturno.servicios.UsuarioService;
import com.agua.enturno.vista.dto.NotificacionDTO;
import com.agua.enturno.vista.dto.UsuarioDTO;
import com.agua.enturno.vista.dto.UsuarioDeSessionDTO;
import com.agua.enturno.vista.dto.assemblers.NotificacionAssembler;
import com.agua.enturno.vista.dto.assemblers.UsuarioAssembler;
import com.agua.enturno.vista.dto.assemblers.UsuarioDeSessionAssembler;
import org.joda.time.DateTime;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

public class UsuarioServiceImpl implements UsuarioService {

	private UsuarioDAO usuarioDAO;
	private UsuarioAssembler usuarioAssembler;
	private UsuarioDeSessionAssembler usuarioDeSessionAssembler;
	private NotificacionAssembler notificacionAssembler;
	
	
	/*------------------------------------ Public methods ----------------------------------*/

	@Override
	@Transactional
	public UsuarioDTO findById(Long id) {
		return usuarioAssembler.assemble(usuarioDAO.findById(id));
	}
	
	@Override
	@Transactional
	public UsuarioDTO findByUsername(String username) {
		return usuarioAssembler.assemble(usuarioDAO.findByUsername(username));
	}
	
	@Override
	@Transactional
	public List<NotificacionDTO> findNotificaciones(Long usuarioId) {
		return notificacionAssembler.assemble(usuarioDAO.findById(usuarioId).getNotificaciones());
	}
	
	@Override
	@Transactional
	public UsuarioDeSessionDTO authenticate(String username, String password) throws ExcepcionDeReglaDelNegocio {
		
		UsuarioDeSessionDTO usuario = usuarioDeSessionAssembler.assemble(usuarioDAO.findByUsername(username));
		
		if ( usuario == null )
			throw new ExcepcionDeReglaDelNegocio("El usuario no existe");
		
		if ( !usuarioDAO.isAuthenticUser(username, password) )
			throw new ExcepcionDeReglaDelNegocio("El password es incorrecto");
			
		return usuario;
	}
	
	@Override
	@Transactional
	public void updateLastLogin(Long usuarioId, DateTime lastLogin) {
		
		Usuario usuario = usuarioDAO.findById(usuarioId);
		usuario.setUltimoLogueo(lastLogin);
	}
	
	@Override
	@Transactional
	public void crearUsuario(UsuarioDTO usuarioDTO) throws ExcepcionDeReglaDelNegocio {
		try {
			
			Usuario usuario = usuarioAssembler.disassemble(usuarioDTO);
			usuario.agregarRol(new Cliente());
			usuarioDAO.saveOrUpdate(usuario);
			
		} catch (DataIntegrityViolationException e) {
			
			usuarioDAO.clearSession();
			throw new ExcepcionDeReglaDelNegocio("Ya existe otro usuario con el mail " + usuarioDTO.getEmail());
		}
	}

	/*--------------------------------------------------------------------------------------*/
	/*---------------------------------- Geters and seters ---------------------------------*/

	public void setUsuarioDAO(UsuarioDAO usuarioDAO) {
		this.usuarioDAO = usuarioDAO;
	}

	public void setUsuarioAssembler(UsuarioAssembler usuarioAssembler) {
		this.usuarioAssembler = usuarioAssembler;
	}

	public void setUsuarioDeSessionAssembler(UsuarioDeSessionAssembler usuarioDeSessionAssembler) {
		this.usuarioDeSessionAssembler = usuarioDeSessionAssembler;
	}

	public void setNotificacionAssembler(NotificacionAssembler notificacionAssembler) {
		this.notificacionAssembler = notificacionAssembler;
	}

	/*--------------------------------------------------------------------------------------*/

}
